package com.zbkj.client.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zbkj.client.enums.WebSocketEventType;
import com.zbkj.client.service.DigitalPersonService;
import com.zbkj.client.task.DpVoiceStatusUpdateTask;
import com.zbkj.client.task.DpVideoStatusUpdateTask;
import com.zbkj.client.vo.AccessTokenResponseVo;
import com.zbkj.client.vo.CreateDpVideoRequestVo;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.model.client.digital.CustomDigitalPerson;
import com.zbkj.common.model.client.digital.DgVideo;
import com.zbkj.common.model.client.digital.DpVoice;
import com.zbkj.common.model.client.digital.PublicDigitalPerson;
import com.zbkj.common.model.client.workbench.VideoTemplateFinal;
import com.zbkj.common.request.client.VideoTemplateRequest;
import com.zbkj.common.response.ClientLoginResponse;
import com.zbkj.common.result.CommonResult;
import com.zbkj.common.utils.RedisUtil;
import com.zbkj.service.service.CustomDigitalPersonService;
import com.zbkj.service.service.DgVideoService;
import com.zbkj.service.service.DpVoiceService;
import com.zbkj.service.service.PublicDigitalPersonService;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

@Slf4j
@Service
public class DigitalPersonServiceImpl implements DigitalPersonService {

    @Value("${digital-person.url}")
    private String digitalPersonUrl;
    @Value("${digital-person.app_id}")
    private String appId;
    @Value("${digital-person.secret_key}")
    private String secretKey;
    @Value("${chanjing.callback_url}")
    private String callbackUrl;


    @Resource
    private RestTemplate restTemplate;
    private static final String ACCESS_TOKEN_KEY = "C:DP:TOKEN";
    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private DgVideoService dgVideoService;

    @Autowired
    private DpVoiceStatusUpdateTask dpVoiceStatusUpdateTask;

    @Autowired
    private DpVoiceService dpVoiceService;

    @Autowired
    private DpVideoStatusUpdateTask dpVideoStatusUpdateTask;

    @Autowired
    private ThreadPoolTaskScheduler taskScheduler;

    @Autowired
    private PublicDigitalPersonService publicDigitalPersonService;

    @Autowired
    private CustomDigitalPersonService customDigitalPersonService;


    private final ObjectMapper objectMapper = new ObjectMapper();

    private final String dpVideoAddUrl = "/open/v1/create_video";
    private final String createDpVideoCallback = "/dp/createDpVideo";
    private final String dpVoiceAddUrl = "/open/v1/create_audio_task";
    private final String createDpVoiceCallback = "/dp/createDpVoice";


    @Override
    public String getAccessToken() {
        String token = redisUtil.get(ACCESS_TOKEN_KEY);
        if (token != null) return token;
        String url = digitalPersonUrl + "/open/v1/access_token";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        Map<String, String> params = new HashMap<>();
        params.put("app_id", appId);
        params.put("secret_key", secretKey);
        HttpEntity<Map<String, String>> entity = new HttpEntity<>(params, headers);
        ResponseEntity<AccessTokenResponseVo> response = restTemplate.exchange(url, HttpMethod.POST, entity, AccessTokenResponseVo.class);
        if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null && response.getBody().getCode() == 0) {
            String accessToken = response.getBody().getData().getAccess_token();
            long expire = response.getBody().getData().getExpire_in();
            long now = System.currentTimeMillis() / 1000;
            redisUtil.set(ACCESS_TOKEN_KEY, accessToken, expire - now - 60); // 提前一分钟过期
            return accessToken;
        }
        throw new RuntimeException("获取access_token失败: " + (response.getBody() != null ? response.getBody().getMsg() : "未知错误"));
    }

    @Override
    public ResponseEntity<String> requestDpVideo(String url, HttpHeaders headers, Map<String, Object> params) {
        HttpEntity<Map<String, Object>> entity = new HttpEntity<>(params, headers);
        return restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
    }

    /**
     * 合成声音-service
     * @param params
     * @param userId
     * @param merId
     * @return
     */
    @Override
    public Map<String, Object> addDpVoice(Map<String, Object> params, Integer userId, Integer merId){

        String accessToken = getAccessToken();
        String url = digitalPersonUrl + dpVoiceAddUrl;
        HttpHeaders headers = new HttpHeaders();
        headers.set("access_token", accessToken);
        headers.setContentType(MediaType.APPLICATION_JSON);

        // 设置回调地址
        params.put("callback", callbackUrl + createDpVoiceCallback);

        //设置默认值，要不然字幕出不来
        params.put("font_size", 64);
        params.put("width", 1000);
        params.put("height", 90);

        HttpEntity<Map<String, Object>> entity = new HttpEntity<>(params, headers);
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);

        // 插入到数据库
        DpVoice dpVoice = new DpVoice();
        dpVoice.setUserId(userId);
        dpVoice.setMerId(merId);
        dpVoice.setType("tts");
        dpVoice.setIsDel(0);
        dpVoice.setCreateTime(new Date());
        dpVoice.setUpdateTime(new Date());
        if (params.get("text") != null) {
            Object textObj = params.get("text");
            if (textObj instanceof Map) {
                Object textValue = ((Map) textObj).get("text");
                if (textValue != null) {
                    dpVoice.setText(textValue.toString());
                }
            }
        }

        try {
            JsonNode root = objectMapper.readTree(response.getBody());
            int code = root.path("code").asInt();
            String msg = root.path("msg").asText();

            String taskId = root.path("data").path("task_id").asText();
            String traceId = root.path("trace_id").asText();

            if (code == 0) {
                dpVoice.setLinkId(taskId);
                dpVoice.setStatus(1); // 生成中
                dpVoiceService.save(dpVoice);
                Integer id = dpVoice.getId();

                //合成声音 定时任务开启
                dpVoiceStatusUpdateTask.start(taskId);

                //成功的返回
                Map<String, Object> result = new HashMap<>();
                result.put("voiceId", taskId);
                result.put("traceId", traceId);
                result.put("id", id);
                result.put("code", 0);
                return result;
            } else {
                dpVoice.setStatus(9); // 生成完毕
                dpVoice.setErrMsg(msg); // 失败原因
                dpVoice.setErrReason(msg); // 生成中
                dpVoiceService.save(dpVoice);

                Integer id = dpVoice.getId();

                Map<String, Object> result = new HashMap<>();
                result.put("code", code);
                result.put("msg", msg);
                result.put("id", id);
                return result;
            }
        } catch (Exception e) {
            log.error("创建语音任务返回异常", e);
//            dpVoice.setLinkId(taskId);
            String errMsg = "创建语音任务异常"+e.getMessage();
            dpVoice.setStatus(9); // 生成完毕
            dpVoice.setErrMsg(errMsg); // 失败原因
            dpVoice.setErrReason(errMsg); // 错误消息
            dpVoiceService.save(dpVoice);
            Integer id = dpVoice.getId();
//            throw new CrmebException("创建语音任务返回异常");

            Map<String, Object> result = new HashMap<>();
            result.put("code", 500);
            result.put("msg", errMsg);
            result.put("id", id);
            return result;
        }
    }

    /**
     * 通用合成视频（支持tts和audio）
     */
    @Override
    public CompletableFuture<Integer> addDpVideoCommon(DgVideo dgVideo, Map<String, Object> params, String type, String audioManId, String text, String voiceId, Integer userId, Integer merId,  String name, Map<String, Object> saveLocation) {
        Integer id = dgVideo.getId();

        //判断类型，如果是tts 就先合成音频
        String voiceLinkId = "";

        if ("tts".equalsIgnoreCase(type)) {
            Map<String, Object> dpVoiceParams = createDpVoiceParams(audioManId, text);

            Map<String, Object> dpVoiceRes = addDpVoice(dpVoiceParams, userId, merId);
            if (dpVoiceRes.get("code").equals(0)){
//                    DpVoice dpVoiceTemp = dpVoiceService.lambdaQuery()
//                            .eq(DpVoice::getLinkId, dpVoiceRes.get("voiceId"))
//                            .one();
//
//                    dpVoiceId = dpVoiceTemp.getId();
                voiceLinkId = (String) dpVoiceRes.get("voiceId");
            }else{
                // 合成音频失败，直接返回，并将数据库status更新为3
                String errMsg = dpVoiceRes.get("msg").toString();
                log.error("合成数字人视频【合成音频】失败, id:{}, 失败原因：{}", id, errMsg);
                dgVideo.setStatus(500);

                //即使失败了也会有dpvoiceid
                Integer dpVoiceLogicId = (Integer) dpVoiceRes.get("id");
                dgVideo.setVoiceId(dpVoiceLogicId);
                dgVideo.setMsg(errMsg);
                dgVideoService.updateById(dgVideo);

                //推送ws事件
//                String eventName = WebSocketEventType.AddDpVideoFail.name();
//                pushWsEvent(finalId, userId, 3, eventName);
                return CompletableFuture.completedFuture(id);
            }
        }

        CompletableFuture<Integer> future = new CompletableFuture<>();
        // 4. 定时任务，轮询合成声音状态
        final String finalVoiceId = (voiceId != null && !voiceId.isEmpty()) ? voiceId : voiceLinkId;
        final int[] retryCount = {0};
        final Integer[] resultId = {null};
        Runnable checkTask = new Runnable() {
            @Override
            public void run() {
                DpVoice record = dpVoiceService.lambdaQuery().eq(DpVoice::getLinkId, finalVoiceId).one();
                if (record == null) {
                    log.warn("合成视频-未找到合成声音记录，linkId={}", finalVoiceId);
                    // 更新表中这条失败的数据
                    dgVideo.setStatus(500); // 生成中
                    dgVideo.setMsg("合成声音记录不存在");
                    dgVideo.setUpdateTime(new Date());
                    dgVideoService.updateById(dgVideo);
                    future.complete(id);
                    return;
                }
                if (record.getStatus() != null && record.getStatus() != 1 && record.getUrl() != null && !record.getUrl().isEmpty() && record.getDuration() != null) {
                    // 将声音合成后的url写入params.audio.wav_url
                    if (params.containsKey("audio") && params.get("audio") instanceof Map) {
                        Map<String, Object> audioMap = (Map<String, Object>) params.get("audio");
                        audioMap.put("wav_url", record.getUrl());
                    } else {
                        Map<String, Object> audioMap = new HashMap<>();
                        audioMap.put("wav_url", record.getUrl());
                        params.put("audio", audioMap);
                    }
                    // 声音合成完成，自动合成视频
                    Integer id1 = addDpVideo(id, params, userId, merId);

                    //更新video表中的voiceId
                    dgVideo.setVoiceId(record.getId());
                    dgVideo.setUpdateTime(new Date());
                    dgVideoService.updateById(dgVideo);

                    future.complete(id);
                    log.info("定时任务-声音合成完成，自动发起视频合成，voiceId={}", finalVoiceId);
                    return;
                }
                if (record.getStatus() != null && record.getStatus() == 1 && retryCount[0] < 5) {
                    retryCount[0]++;
                    log.info("定时任务-声音未完成，1分钟后重试，voiceId={}, retry={}", finalVoiceId, retryCount[0]);
                    // 1分钟后重试
                    taskScheduler.schedule(this, new Date(System.currentTimeMillis() + 60 * 1000));
                } else if (record.getStatus() != null && record.getStatus() == 9 &&  (record.getErrMsg() != null || record.getErrReason() != null)) {
                    // 更新表中这条失败的数据
                    dgVideo.setStatus(500); // 生成中
                    dgVideo.setMsg(record.getErrMsg());
                    dgVideo.setUpdateTime(new Date());
                    dgVideoService.updateById(dgVideo);
                    future.complete(id);
                    log.warn("合成视频-audio方式声音合成失败，voiceId={}", finalVoiceId);
                }else if (retryCount[0] >= 5) {
                    // 更新表中这条失败的数据
                    dgVideo.setStatus(500); // 生成中
                    dgVideo.setMsg("合成声音失败，请重新操作");
                    dgVideo.setUpdateTime(new Date());
                    dgVideoService.updateById(dgVideo);
                    future.complete(id);

                    log.warn("定时任务-声音合成重试5次仍未完成，voiceId={}", finalVoiceId);
                }
            }
        };
        // 首次1分钟后执行
        taskScheduler.schedule(checkTask, new Date(System.currentTimeMillis() + 60 * 1000));
        return future;
    }

    /**
     * 模板成片的合成视频，先分成两个方法，有时间再整理代码
     */
    @Override
    public CompletableFuture<Integer> addDpVideoTemplate(DgVideo dgVideo, Map<String, Object> params, String type, String audioManId, String text, String voiceId, Integer userId, Integer merId,  String name, Map<String, Object> saveLocation) {
        Integer id = dgVideo.getId();
        // 1. 判断类型
        if ("tts".equalsIgnoreCase(type)) {
            // 2. tts类型，直接合成视频
            return CompletableFuture.completedFuture(addDpVideo(id, params, userId, merId));
        } else if ("audio".equalsIgnoreCase(type)) {
            CompletableFuture<Integer> future = new CompletableFuture<>();
            // 4. 定时任务，轮询合成声音状态
            final String finalVoiceId = voiceId;
            final int[] retryCount = {0};
            final Integer[] resultId = {null};
            Runnable checkTask = new Runnable() {
                @Override
                public void run() {
                    DpVoice record = dpVoiceService.lambdaQuery().eq(DpVoice::getLinkId, finalVoiceId).one();
                    if (record == null) {
                        log.warn("合成视频-未找到合成声音记录，linkId={}", finalVoiceId);
                        // 更新表中这条失败的数据
                        dgVideo.setStatus(500); // 生成中
                        dgVideo.setMsg("合成声音记录不存在");
                        dgVideo.setUpdateTime(new Date());
                        dgVideoService.updateById(dgVideo);
                        future.complete(id);
                        return;
                    }
                    if (record.getStatus() != null && record.getStatus() != 1 && record.getUrl() != null && !record.getUrl().isEmpty() && record.getDuration() != null) {
                        // 将声音合成后的url写入params.audio.wav_url
                        if (params.containsKey("audio") && params.get("audio") instanceof Map) {
                            Map<String, Object> audioMap = (Map<String, Object>) params.get("audio");
                            audioMap.put("wav_url", record.getUrl());
                        } else {
                            Map<String, Object> audioMap = new HashMap<>();
                            audioMap.put("wav_url", record.getUrl());
                            params.put("audio", audioMap);
                        }
                        // 声音合成完成，自动合成视频
                        Integer id1 = addDpVideo(id, params, userId, merId);

                        //更新video表中的voiceId
                        dgVideo.setVoiceId(record.getId());
                        dgVideo.setUpdateTime(new Date());
                        dgVideoService.updateById(dgVideo);

                        future.complete(id);
                        log.info("定时任务-声音合成完成，自动发起视频合成，voiceId={}", finalVoiceId);
                        return;
                    }
                    if (record.getStatus() != null && record.getStatus() == 1 && retryCount[0] < 5) {
                        retryCount[0]++;
                        log.info("定时任务-声音未完成，1分钟后重试，voiceId={}, retry={}", finalVoiceId, retryCount[0]);
                        // 1分钟后重试
                        taskScheduler.schedule(this, new Date(System.currentTimeMillis() + 60 * 1000));
                    } else if (record.getStatus() != null && record.getStatus() == 9 &&  (record.getErrMsg() != null || record.getErrReason() != null)) {
                        // 更新表中这条失败的数据
                        dgVideo.setStatus(500); // 生成中
                        dgVideo.setMsg(record.getErrMsg());
                        dgVideo.setUpdateTime(new Date());
                        dgVideoService.updateById(dgVideo);
                        future.complete(id);
                        log.warn("合成视频-audio方式声音合成失败，voiceId={}", finalVoiceId);
                    }else if (retryCount[0] >= 5) {
                        // 更新表中这条失败的数据
                        dgVideo.setStatus(500); // 生成中
                        dgVideo.setMsg("合成声音失败，请重新操作");
                        dgVideo.setUpdateTime(new Date());
                        dgVideoService.updateById(dgVideo);
                        future.complete(id);

                        log.warn("定时任务-声音合成重试5次仍未完成，voiceId={}", finalVoiceId);
                    }
                }
            };
            // 首次1分钟后执行
            taskScheduler.schedule(checkTask, new Date(System.currentTimeMillis() + 60 * 1000));
            return future;
        }
        return CompletableFuture.completedFuture(id);
    }

    @Override
    public Integer addDpVideo(Integer id, Map<String, Object> params, Integer userId, Integer merId) {
        String accessToken = getAccessToken();
        String url = digitalPersonUrl + dpVideoAddUrl;
        HttpHeaders headers = new HttpHeaders();
        headers.set("access_token", accessToken);
        headers.setContentType(MediaType.APPLICATION_JSON);

        params.put("callback", callbackUrl + createDpVideoCallback);

        DgVideo dgVideo = dgVideoService.getById(id);

        HttpEntity<Map<String, Object>> entity = new HttpEntity<>(params, headers);
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
        try {
            JsonNode root = objectMapper.readTree(response.getBody());
            int code = root.path("code").asInt();
            String msg = root.path("msg").asText();

            String data = root.path("data").asText();
            String traceId = root.path("trace_id").asText();

            if (code == 0) {
                // 更新数据库中的蝉镜linkID
                dgVideo.setLinkId(data);
                dgVideoService.updateById(dgVideo);

                //合成视频提交成功则启动更新合成视频状态定时任务
                log.info("合成视频提交成功,返回的合成数字人任务linkId为：{}, 启动定时任务",data);
                dpVideoStatusUpdateTask.start(data);
            } else {
                // 插入到数据库
                //dgVideo.setLinkId(data);
                dgVideo.setMsg(msg); // 失败的状态
                dgVideo.setStatus(code); // 错误信息
                dgVideoService.updateById(dgVideo);
                log.info("合成视频提交失败,错误信息为：{}-{}",code, msg);
            }

            return id;
        } catch (Exception e) {
            String msg = e.getMessage();
            log.error("创建数字人视频返回异常", msg);
            dgVideo.setMsg("创建数字人视频返回异常" + msg); // 失败的状态
            dgVideo.setStatus(500); // 错误信息
            return id;
        }
    }

    /**
     * 插入到dpVideo表中
     * @param userId
     * @param merId
     * @return
     */
    @Override
    public DgVideo insertDpVideo(Integer userId, Integer merId,String name, Map<String, Object> saveLocation) {
        DgVideo dgVideo = new DgVideo();
        dgVideo.setCreateTime(new Date());
        dgVideo.setUpdateTime(new Date());
        dgVideo.setIsDel(0);
        dgVideo.setUserId(userId);
        dgVideo.setMerId(merId);
        dgVideo.setSaveLocation(saveLocation);
        dgVideo.setName(name);
        dgVideoService.save(dgVideo);

        return dgVideo;
    }

    /**
     * 插入到dpVideo表中
     * @param userId
     * @param merId
     * @return
     */
    @Override
    public DgVideo insertDpVideo(Integer userId, Integer merId,String name, Map<String, Object> saveLocation, CreateDpVideoRequestVo createDpVideoRequestVo) {
        DgVideo dgVideo = new DgVideo();
        dgVideo.setCreateTime(new Date());
        dgVideo.setUpdateTime(new Date());
        dgVideo.setIsDel(0);
        dgVideo.setUserId(userId);
        dgVideo.setMerId(merId);
        dgVideo.setSaveLocation(saveLocation);
        dgVideo.setName(name);

        // 从合成数字人页面进来的
        dgVideo.setAudioType(createDpVideoRequestVo.getType());
        dgVideo.setDpManId(createDpVideoRequestVo.getLinkId());
        dgVideo.setAudioManId(createDpVideoRequestVo.getAudioManId());
        dgVideo.setSource(createDpVideoRequestVo.getSource());
        dgVideo.setSourceId(createDpVideoRequestVo.getSourceId());
        dgVideo.setIsCommonDp(createDpVideoRequestVo.getIsCommonDp());

        Integer isCommonDp = createDpVideoRequestVo.getIsCommonDp();
        if (isCommonDp == 1) {
            PublicDigitalPerson publicDigitalPerson = publicDigitalPersonService.lambdaQuery()
                    .eq(PublicDigitalPerson::getLinkId, createDpVideoRequestVo.getLinkId())
                    .one();

            if(publicDigitalPerson != null) {
                String figures = publicDigitalPerson.getFigure();
                List<Map<String, Object>> figureList = null;
                try {
                    figureList = objectMapper.readValue(figures, new TypeReference<List<Map<String, Object>>>() {});
                } catch (Exception e) {
                    log.error("解析figures字符串失败: {}", e.getMessage(), e);
                }

                for (Map<String, Object> figure : figureList) {
                    if ("sit_body".equals(figure.get("type"))){
                        String dpPreviewVideoUrl = (String)figure.get("preview_video_url");
                        dgVideo.setDpPreviewUrl(dpPreviewVideoUrl);
                        break;
                    }
                }
            }
        }else{
            CustomDigitalPerson customDigitalPerson = customDigitalPersonService.lambdaQuery()
                    .eq(CustomDigitalPerson::getLinkId, createDpVideoRequestVo.getLinkId())
                    .one();

            if(customDigitalPerson != null) {
                dgVideo.setDpPreviewUrl(customDigitalPerson.getOssPreviewUrl());
            }
        }

        dgVideoService.save(dgVideo);

        return dgVideo;
    }

    /**
     * 模板成片插入到dpVideo表中
     * @param userId
     * @param merId
     * @return
     */
    @Override
    public DgVideo insertDpVideo(Integer userId, Integer merId,String name, Map<String, Object> sourceMap, VideoTemplateRequest videoTemplateRequest, Integer voiceId) {
        DgVideo dgVideo = new DgVideo();
        dgVideo.setCreateTime(new Date());
        dgVideo.setUpdateTime(new Date());
        dgVideo.setIsDel(0);
        dgVideo.setUserId(userId);
        dgVideo.setMerId(merId);
//        dgVideo.setSaveLocation(saveLocation);
        dgVideo.setName(name);

        //从模板成片的页面过来的
        dgVideo.setAudioType(videoTemplateRequest.getVideoType());
        dgVideo.setDpManId(videoTemplateRequest.getDpManLinkId());
        dgVideo.setAudioManId(videoTemplateRequest.getAudioManLinkId());
        dgVideo.setIsCommonDp(videoTemplateRequest.getIsCommonDp());
        dgVideo.setSource((String) sourceMap.get("sourceName"));
        dgVideo.setSourceId((Integer) sourceMap.get("sourceId"));
        dgVideo.setVoiceId(voiceId);

        Integer isCommonDp = videoTemplateRequest.getIsCommonDp();
        if (isCommonDp == 1) {
            PublicDigitalPerson publicDigitalPerson = publicDigitalPersonService.lambdaQuery()
                    .eq(PublicDigitalPerson::getLinkId, videoTemplateRequest.getDpManLinkId())
                    .one();

            if(publicDigitalPerson != null) {
                String figures = publicDigitalPerson.getFigure();
                List<Map<String, Object>> figureList = null;
                try {
                    figureList = objectMapper.readValue(figures, new TypeReference<List<Map<String, Object>>>() {});
                } catch (Exception e) {
                    log.error("解析figures字符串失败: {}", e.getMessage(), e);
                }

                for (Map<String, Object> figure : figureList) {
                    if ("sit_body".equals(figure.get("type"))){
                        String dpPreviewVideoUrl = (String)figure.get("preview_video_url");
                        dgVideo.setDpPreviewUrl(dpPreviewVideoUrl);
                        break;
                    }
                }
            }
        }else{
            CustomDigitalPerson customDigitalPerson = customDigitalPersonService.lambdaQuery()
                    .eq(CustomDigitalPerson::getLinkId, videoTemplateRequest.getDpManLinkId())
                    .one();

            if(customDigitalPerson != null) {
                dgVideo.setDpPreviewUrl(customDigitalPerson.getOssPreviewUrl());
            }
        }

        dgVideoService.save(dgVideo);

        return dgVideo;
    }

    /**
     * 合成声音参数构建
     * @return
     */
    private Map<String, Object> createDpVoiceParams(String audioManId, String text) {
        // 构建请求参数
        Map<String, Object> params = new HashMap<>();
        params.put("audio_man", audioManId);
        params.put("speed", 1.1);
        params.put("pitch", 1);

        // 设置文本内容
        if (text != null && !text.isEmpty()) {
            Map<String, Object> textMap = new HashMap<>();
            textMap.put("text", text);
            textMap.put("plain_text", text);
            params.put("text", textMap);
        }

        return params;
    }
} 